﻿"""Application configuration settings."""

from __future__ import annotations

from functools import lru_cache
from pathlib import Path

from pydantic import AnyHttpUrl, Field, BaseModel
from pydantic_settings import BaseSettings, SettingsConfigDict


class AnalysisScoringSettings(BaseModel):
    """Default heuristic scoring thresholds."""

    priority_weights: dict[str, int] = Field(
        default_factory=lambda: {"high": 3, "medium": 2, "low": 1},
        description="Weight mapping applied to requirement priorities.",
    )
    simple_requirement_count_max: int = Field(
        5, description="Max requirements for simple complexity."
    )
    simple_average_priority_ceiling: float = Field(
        2.0, description="Average priority ceiling for simple complexity."
    )
    medium_requirement_count_max: int = Field(
        12, description="Max requirements still considered medium complexity."
    )
    medium_average_priority_ceiling: float = Field(
        2.3, description="Average priority ceiling for medium complexity."
    )
    clarifying_high_ratio: float = Field(
        0.4, description="Clarifying requirement ratio that triggers high risk."
    )
    baselined_low_risk_ratio: float = Field(
        0.5, description="Baselined ratio that downgrades risk to low."
    )
    baseline_health_min_ratio: float = Field(
        0.25, description="Minimum baselined ratio before warning recommendation."
    )
    low_score_intervention_threshold: float = Field(
        60.0, description="Overall score under which to recommend remediation."
    )
    score_high_threshold: float = Field(75.0, description="Score tag boundary for high readiness.")
    score_medium_threshold: float = Field(
        50.0, description="Score tag boundary for medium readiness."
    )
    priority_score_weight: float = Field(
        0.4, description="Weight applied to priority alignment component."
    )
    clarity_score_weight: float = Field(0.3, description="Weight applied to clarity component.")
    baseline_score_weight: float = Field(
        0.3, description="Weight applied to baselined coverage component."
    )


def _build_default_analysis_scoring() -> AnalysisScoringSettings:
    """Return the default scoring settings instance."""

    return AnalysisScoringSettings.model_validate({})


class Settings(BaseSettings):
    """Strongly typed application settings."""

    # Calculate absolute path to .env file (3 levels up from this file)
    _env_file = str(Path(__file__).parent.parent.parent.parent / ".env")
    model_config = SettingsConfigDict(env_file=_env_file, env_file_encoding="utf-8")

    APP_NAME: str = "n8n Consulting Backend"
    API_V1_STR: str = "/api/v1"
    SECRET_KEY: str
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30  # 默认30分钟
    ACCESS_TOKEN_EXPIRE_DAYS_REMEMBER: int = 30  # "记住我"时30天
    REFRESH_TOKEN_EXPIRE_DAYS: int = 7
    PASSWORD_RESET_TOKEN_EXPIRE_MINUTES: int = 30

    SQLALCHEMY_DATABASE_URI: str = Field(
        ...,
        description="Database connection string (will be auto-converted to sync), e.g. sqlite+aiosqlite:///./app.db",
    )
    DB_ECHO: bool = False

    BACKEND_CORS_ORIGINS: list[AnyHttpUrl] = Field(default_factory=list)
    CORS_ORIGIN_REGEX: str | None = Field(
        default=None,
        description="CORS origin regex pattern (fallback when BACKEND_CORS_ORIGINS is empty)",
    )

    AI_PROVIDER: str = Field(default="glm", pattern="^(openai|dashscope|glm|qwen|hunyuan)$")
    OPENAI_API_KEY: str | None = None
    DASHSCOPE_API_KEY: str | None = None

    # AI 模型配置 (多提供商 - 按优先级排序)
    GLM_API_KEY: str | None = None  # 智谱AI GLM-4-Flash (免费，优先使用)
    QWEN_API_KEY: str | None = None  # 阿里云通义千问 Qwen-turbo
    HUNYUAN_SECRET_ID: str | None = None  # 腾讯混元 Hunyuan-lite SecretId
    HUNYUAN_SECRET_KEY: str | None = None  # 腾讯混元 Hunyuan-lite SecretKey

    SMTP_HOST: str | None = None
    SMTP_PORT: int = 587
    SMTP_USERNAME: str | None = None
    SMTP_PASSWORD: str | None = None

    FRONTEND_BASE_URL: str | None = Field(
        default=None, description="Base URL used for building email links"
    )
    PASSWORD_RESET_PATH: str = Field(
        default="/reset-password", description="Relative path for password reset page"
    )
    MEDIA_ROOT: str = Field(default="./storage", description="Root directory for stored files")
    REQUIREMENT_ATTACHMENT_DIR: str = Field(
        default="requirements", description="Subdirectory for requirement attachments"
    )
    ANALYSIS_SCORING: AnalysisScoringSettings = Field(
        default_factory=_build_default_analysis_scoring,
        description="Default scoring thresholds used to generate project analysis heuristics.",
    )


@lru_cache()
def get_settings() -> Settings:
    return Settings()  # type: ignore[call-arg]


settings = get_settings()
